From: Keir Fraser Date: Mon, 13 Jul 2009 10:32:41 +0000 (+0100) Subject: Introduce and use a per-CPU read-mostly sub-section X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13615 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=cfbf17ffbb03e8c8501cae1bbba5459450b3447c;p=xen.git Introduce and use a per-CPU read-mostly sub-section Since mixing data that only gets setup once and then (perhaps frequently) gets read by remote CPUs with data that the local CPU may modify (again, perhaps frequently) still causes undesirable cache protocol related bus traffic, separate the former class of objects from the latter. These objects converted here are just picked based on their write-once (or write-very-rarely) properties; perhaps some more adjustments may be desirable subsequently. The primary users of the new sub-section will result from the next patch. Signed-off-by: Jan Beulich --- diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c index f1689df0f4..1872f12d09 100644 --- a/xen/arch/ia64/xen/vhpt.c +++ b/xen/arch/ia64/xen/vhpt.c @@ -21,8 +21,8 @@ #include #include -DEFINE_PER_CPU (unsigned long, vhpt_paddr); -DEFINE_PER_CPU (unsigned long, vhpt_pend); +DEFINE_PER_CPU_READ_MOSTLY(unsigned long, vhpt_paddr); +DEFINE_PER_CPU_READ_MOSTLY(unsigned long, vhpt_pend); #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK DEFINE_PER_CPU(volatile u32, vhpt_tlbflush_timestamp); #endif diff --git a/xen/arch/ia64/xen/xen.lds.S b/xen/arch/ia64/xen/xen.lds.S index 4daf6adfb9..2fe1905f25 100644 --- a/xen/arch/ia64/xen/xen.lds.S +++ b/xen/arch/ia64/xen/xen.lds.S @@ -187,6 +187,8 @@ SECTIONS { __per_cpu_start = .; *(.data.percpu) + . = ALIGN(SMP_CACHE_BYTES); + *(.data.percpu.read_mostly) __per_cpu_end = .; } . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 4a30a7d395..7a53d46358 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -66,7 +66,7 @@ u32 vmx_vmexit_control __read_mostly; u32 vmx_vmentry_control __read_mostly; bool_t cpu_has_vmx_ins_outs_instr_info __read_mostly; -static DEFINE_PER_CPU(struct vmcs_struct *, host_vmcs); +static DEFINE_PER_CPU_READ_MOSTLY(struct vmcs_struct *, host_vmcs); static DEFINE_PER_CPU(struct vmcs_struct *, current_vmcs); static DEFINE_PER_CPU(struct list_head, active_vmcs_list); diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 8fb5bcdd6f..ec060eadfa 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -111,9 +111,9 @@ extern void vesa_init(void); extern void vesa_mtrr_init(void); extern void init_tmem(void); -DEFINE_PER_CPU(struct desc_struct *, gdt_table) = boot_cpu_gdt_table; +DEFINE_PER_CPU_READ_MOSTLY(struct desc_struct *, gdt_table) = boot_cpu_gdt_table; #ifdef CONFIG_COMPAT -DEFINE_PER_CPU(struct desc_struct *, compat_gdt_table) +DEFINE_PER_CPU_READ_MOSTLY(struct desc_struct *, compat_gdt_table) = boot_cpu_compat_gdt_table; #endif diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index a2adcfa26a..d749d268c1 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -78,7 +78,7 @@ char opt_nmi[10] = "fatal"; #endif string_param("nmi", opt_nmi); -DEFINE_PER_CPU(u32, ler_msr); +DEFINE_PER_CPU_READ_MOSTLY(u32, ler_msr); /* Master table, used by CPU0. */ idt_entry_t idt_table[IDT_ENTRIES]; diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 406098046c..c58e5e2918 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -188,7 +188,7 @@ void show_page_walk(unsigned long addr) unmap_domain_page(l1t); } -DEFINE_PER_CPU(struct tss_struct *, doublefault_tss); +DEFINE_PER_CPU_READ_MOSTLY(struct tss_struct *, doublefault_tss); static unsigned char __attribute__ ((__section__ (".bss.page_aligned"))) boot_cpu_doublefault_space[PAGE_SIZE]; diff --git a/xen/arch/x86/x86_32/xen.lds.S b/xen/arch/x86/x86_32/xen.lds.S index 1bbb65405a..d4afcc58a7 100644 --- a/xen/arch/x86/x86_32/xen.lds.S +++ b/xen/arch/x86/x86_32/xen.lds.S @@ -4,6 +4,7 @@ */ #include +#include #include #include #undef ENTRY @@ -69,9 +70,13 @@ SECTIONS __init_end = .; __per_cpu_shift = PERCPU_SHIFT; /* kdump assist */ - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } :text - __per_cpu_data_end = .; + .data.percpu : { + __per_cpu_start = .; + *(.data.percpu) + . = ALIGN(SMP_CACHE_BYTES); + *(.data.percpu.read_mostly) + __per_cpu_data_end = .; + } :text . = __per_cpu_start + (NR_CPUS << PERCPU_SHIFT); . = ALIGN(PAGE_SIZE); __per_cpu_end = .; diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index 4fafb904a9..87b8957ff5 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -37,7 +37,7 @@ unsigned int m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START; #endif -DEFINE_PER_CPU(void *, compat_arg_xlat); +DEFINE_PER_CPU_READ_MOSTLY(void *, compat_arg_xlat); /* Top-level master (and idle-domain) page directory. */ l4_pgentry_t __attribute__ ((__section__ (".bss.page_aligned"))) diff --git a/xen/arch/x86/x86_64/xen.lds.S b/xen/arch/x86/x86_64/xen.lds.S index f6c37f02cc..8ef209841e 100644 --- a/xen/arch/x86/x86_64/xen.lds.S +++ b/xen/arch/x86/x86_64/xen.lds.S @@ -2,6 +2,7 @@ /* Modified for x86-64 Xen by Keir Fraser */ #include +#include #include #include #undef ENTRY @@ -67,9 +68,13 @@ SECTIONS __init_end = .; __per_cpu_shift = PERCPU_SHIFT; /* kdump assist */ - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } :text - __per_cpu_data_end = .; + .data.percpu : { + __per_cpu_start = .; + *(.data.percpu) + . = ALIGN(SMP_CACHE_BYTES); + *(.data.percpu.read_mostly) + __per_cpu_data_end = .; + } :text . = __per_cpu_start + (NR_CPUS << PERCPU_SHIFT); . = ALIGN(PAGE_SIZE); __per_cpu_end = .; diff --git a/xen/common/kexec.c b/xen/common/kexec.c index baa4a657e9..bb9fdf90a7 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -27,7 +27,7 @@ #include #endif -static DEFINE_PER_CPU(void *, crash_notes); +static DEFINE_PER_CPU_READ_MOSTLY(void *, crash_notes); static Elf_Note *xen_crash_note; diff --git a/xen/common/tmem_xen.c b/xen/common/tmem_xen.c index 9911e802ed..f1b94239f4 100644 --- a/xen/common/tmem_xen.c +++ b/xen/common/tmem_xen.c @@ -36,8 +36,8 @@ DECL_CYC_COUNTER(pg_copy); * allocated iff opt_tmem_compress */ #define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS #define LZO_DSTMEM_PAGES 2 -static DEFINE_PER_CPU(unsigned char *, workmem); -static DEFINE_PER_CPU(unsigned char *, dstmem); +static DEFINE_PER_CPU_READ_MOSTLY(unsigned char *, workmem); +static DEFINE_PER_CPU_READ_MOSTLY(unsigned char *, dstmem); #ifdef COMPARE_COPY_PAGE_SSE2 #include /* REMOVE ME AFTER TEST */ diff --git a/xen/common/trace.c b/xen/common/trace.c index 38113d21df..594a3d68a0 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -46,8 +46,8 @@ static unsigned int opt_tbuf_size = 0; integer_param("tbuf_size", opt_tbuf_size); /* Pointers to the meta-data objects for all system trace buffers */ -static DEFINE_PER_CPU(struct t_buf *, t_bufs); -static DEFINE_PER_CPU(unsigned char *, t_data); +static DEFINE_PER_CPU_READ_MOSTLY(struct t_buf *, t_bufs); +static DEFINE_PER_CPU_READ_MOSTLY(unsigned char *, t_data); static int data_size; /* High water mark for trace buffers; */ diff --git a/xen/include/asm-ia64/linux-xen/asm/percpu.h b/xen/include/asm-ia64/linux-xen/asm/percpu.h index 8642afe792..3bd030327c 100644 --- a/xen/include/asm-ia64/linux-xen/asm/percpu.h +++ b/xen/include/asm-ia64/linux-xen/asm/percpu.h @@ -26,9 +26,9 @@ extern __SMALL_ADDR_AREA __typeof__(type) per_cpu__##name /* Separate out the type, so (int[3], foo) works. */ -#define DEFINE_PER_CPU(type, name) \ - __attribute__((__section__(".data.percpu"))) \ - __SMALL_ADDR_AREA __typeof__(type) per_cpu__##name +#define __DEFINE_PER_CPU(type, name, suffix) \ + __attribute__((__section__(".data.percpu" #suffix))) \ + __SMALL_ADDR_AREA __typeof__(type) per_cpu_##name /* * Pretty much a literal copy of asm-generic/percpu.h, except that percpu_modcopy() is an diff --git a/xen/include/asm-x86/percpu.h b/xen/include/asm-x86/percpu.h index d76206587f..ad5c667ace 100644 --- a/xen/include/asm-x86/percpu.h +++ b/xen/include/asm-x86/percpu.h @@ -5,9 +5,9 @@ #define PERCPU_SIZE (1UL << PERCPU_SHIFT) /* Separate out the type, so (int[3], foo) works. */ -#define DEFINE_PER_CPU(type, name) \ - __attribute__((__section__(".data.percpu"))) \ - __typeof__(type) per_cpu__##name +#define __DEFINE_PER_CPU(type, name, suffix) \ + __attribute__((__section__(".data.percpu" #suffix))) \ + __typeof__(type) per_cpu_##name /* var is in discarded region: offset to particular copy we want */ #define per_cpu(var, cpu) \ diff --git a/xen/include/xen/percpu.h b/xen/include/xen/percpu.h index 34635892a5..9366d18750 100644 --- a/xen/include/xen/percpu.h +++ b/xen/include/xen/percpu.h @@ -4,6 +4,16 @@ #include #include +/* + * Separate out the type, so (int[3], foo) works. + * + * The _##name concatenation is being used here to prevent 'name' from getting + * macro expanded, while still allowing a per-architecture symbol name prefix. + */ +#define DEFINE_PER_CPU(type, name) __DEFINE_PER_CPU(type, _##name, ) +#define DEFINE_PER_CPU_READ_MOSTLY(type, name) \ + __DEFINE_PER_CPU(type, _##name, .read_mostly) + /* Preferred on Xen. Also see arch-defined per_cpu(). */ #define this_cpu(var) __get_cpu_var(var)